
通过为整个类型定义一个新名称，可以使类模板使用起来更简单。

\hspace*{\fill} \\ %插入空行
\noindent
\textbf{类型定义和别名声明}

有两种方法类型定义新名称:

\begin{enumerate}
\item
通过使用关键字typedef:

\begin{lstlisting}[style=styleCXX]
typedef Stack<int> IntStack; // typedef
void foo (IntStack const& s); // s is stack of ints
IntStack istack[10]; // istack is array of 10 stacks of ints
\end{lstlisting}

typedef产生的名称称为typedef-name。

\begin{tcolorbox}[colback=webgreen!5!white,colframe=webgreen!75!black]
\hspace*{0.75cm}这里使用了typedef，而不是“类型定义”。其实，关键字typedef最初是用来建议“类型定义”的。在C++中，“类型定义”实际上意味着其他类型(例如，类或枚举类型的定义)。相反，应该将typedef视为现有类型的替代名称(“别名”)，从而使用typedef。
\end{tcolorbox}

\item
通过使用关键字using(C++11起):

\begin{lstlisting}[style=styleCXX]
using IntStack = Stack<int>; // alias declaration
void foo (IntStack const& s); // s is stack of ints
IntStack istack[10]; // istack is array of 10 stacks of ints
\end{lstlisting}

由[dosreismarcusaliastemplate]引入，称为别名声明。

\end{enumerate}

两种情况下，都会为现有类型定义新名称。因此，

\begin{lstlisting}[style=styleCXX]
typedef Stack<int> IntStack;
\end{lstlisting}

或

\begin{lstlisting}[style=styleCXX]
using IntStack = Stack<int>;
\end{lstlisting}

IntStack和Stack<int>是同一类型的两种名称。

作为为现有类型定义新名称的通用术语，可以用其来声明别名。因此，新名称就是原类型的别名。

将已定义的类型名放在等号左边，阅读起来更容易，所以在本书声明类型别名时，更倾向使用别名声明语法。

\hspace*{\fill} \\ %插入空行
\noindent
\textbf{模板别名}

与typedef不同，别名声明可以模板化。自C++11起，这种方式就称为别名模板。

\begin{tcolorbox}[colback=webgreen!5!white,colframe=webgreen!75!black]
\hspace*{0.75cm}别名模板有时(不正确地)会称为typedef模板，若将其制成模板，将与typedef的行为相同。
\end{tcolorbox}

别名模板DequeStack，对元素类型T进行参数化，展开为一个栈，将其元素实例存储在std::deque:

\begin{lstlisting}[style=styleCXX]
template<typename T>
using DequeStack = Stack<T, std::deque<T>>;
\end{lstlisting}

因此，类模板和别名模板都可以作为参数化类型。但别名模板只是为现有类型提供一个新名称，该类型仍然可以使用。DequeStack<int>和Stack<int, std::deque<int>>表示的就是相同类型。

通常情况下，模板只能在全局/命名空间作用域或类声明内部声明和定义。

\hspace*{\fill} \\ %插入空行
\noindent
\textbf{成员类型的别名模板}

别名模板对于制作类模板成员类型的快捷方式特别合适。比如：

\begin{lstlisting}[style=styleCXX]
template<typename T> struct MyType {
	typedef ... iterator;
	...
};
\end{lstlisting}

或

\begin{lstlisting}[style=styleCXX]
template<typename T> struct MyType {
	using iterator = ...;
	...
};
\end{lstlisting}

可以这样的定义

\begin{lstlisting}[style=styleCXX]
template<typename T>
using MyTypeIterator = typename MyType<T>::iterator;
\end{lstlisting}

也可以这样

\begin{lstlisting}[style=styleCXX]
MyTypeIterator<T> pos;
\end{lstlisting}

而不像下面这样:

\begin{lstlisting}[style=styleCXX]
typename MyType<T>::iterator pos;
\end{lstlisting}

\begin{tcolorbox}[colback=webgreen!5!white,colframe=webgreen!75!black]
\hspace*{0.75cm}因为成员是类型，所以typename是必要的。参见5.1节。
\end{tcolorbox}

\hspace*{\fill} \\ %插入空行
\noindent
\textbf{类型特征后缀\_t}

C++14后，标准库使用这种方式为库中的所有类型定义了快捷方式。比如:

\begin{lstlisting}[style=styleCXX]
std::add_const_t<T> // since C++14
\end{lstlisting}

而非

\begin{lstlisting}[style=styleCXX]
typename std::add_const<T>::type // since C++11
\end{lstlisting}

标准库定义:

\begin{lstlisting}[style=styleCXX]
namespace std {
	template<typename T> using add_const_t = typename add_const<T>::type;
}
\end{lstlisting}




